package com.zhanghp.class04;

/**
 * <h1>不对！！！需要重新处理</h1>
 * <h1>用位数实现加减乘除</h1>
 * <a href="https://leetcode.cn/problems/divide-two-integers">相除</a>
 *
 * @author zhanghp
 * @since 2023/11/16 20:18
 */
public class Code03_BitAddMinusMultiDiv {

    /**
     * 相加
     *
     * @param a
     * @param b
     * @return
     */
    public static int add(int a, int b) {
        int sum = b;

        while (b != 0) {
            // 相加
            sum = a ^ b;
            // 进位信息
            b = (a & b) << 1;
            // 赋值
            a = sum;
        }
        return a;
    }

    /**
     * 相减
     *
     * @param a
     * @param b
     * @return
     */
    public static int minus(int a, int b) {
        return add(a, negNum(b));
    }

    /**
     * 相乘
     *
     * @param a
     * @param b
     * @return
     */
    public static int multi(int a, int b) {
        int res = 0;
        while (b != 0) {
            if ((b & 1) != 0) {
                res = add(a, res);
            }
            // 乘法右移，相加的目的
            a <<= 1;
            // 无符号右移
            b >>>= 1;
        }
        return res;
    }

    /**
     * <p>相除</p>
     * <p>
     * a / b = c
     * c = 二进制
     * a / b = 2^n + ...
     * a = 2^n * b + ...
     * </p>
     * <p>
     * a 从30位开始移到0，移动到 a >= 2^n * b
     * n就位c的二进制的位数
     * a - b，在继续移动
     * </p>
     *
     * @param a
     * @param b
     * @return
     */
    public static int div(int a, int b) {
        int x = isNeg(a) ? negNum(a) : a;
        int y = isNeg(b) ? negNum(b) : b;
        int res = 0;
        // 设立30的原因：int的类型-2^31 ~ 2^31
        // 第一位是符号位，默认为正
        for (int i = 30; i >= 0; i = minus(i, 1)) {
            if ((x >> i) >= y) {
                res |= (1 << i);
                x = minus(x, y << i);
            }
        }
        return isNeg(a) ^ isNeg(b) ? negNum(res) : res;
    }

    /**
     * <p>解决系统最小值转绝对值的除法</p>
     * <p>int取值范围：-2^31 ~ 2^31 -1</p>
     * <p>所以当临界在-2^31时，没有对应的2^31</p>
     *
     * @param a
     * @param b
     * @return
     */
    public static int divide(int a, int b) {
        if (a == Integer.MIN_VALUE && b == Integer.MIN_VALUE) {
            return 1;
        } else if (b == Integer.MIN_VALUE) {
            // a 不为最小，b为最小
            return 0;
        } else if (a == Integer.MIN_VALUE) {
            if (b == negNum(1)) {
                return Integer.MAX_VALUE;
            } else {
                int c = div(add(a, 1), b);
                return add(c, div(minus(a, multi(b, c)), b));
            }
        } else {
            return div(a, b);
        }
    }


    /**
     * 判断是否为奇数
     *
     * @param a
     * @return
     */
    public static boolean judegeOdd(int a) {
        return (a & 1) == 1;
    }

    /**
     * 取反
     *
     * @param a
     * @return
     */
    public static int negNum(int a) {
        return ~a + 1;
    }

    public static boolean isNeg(int a) {
        return a < 0;
    }

    public static void main(String[] args) {
        System.out.println(add(7, 3));
        System.out.println(minus(7, -3));
        System.out.println(multi(20, -10));
        System.out.println(div(20, 7));
        System.out.println(divide(Integer.MIN_VALUE, -1));

    }
}
